﻿using EmailHelper.Common;
using EmailHelper.Model;
using MailKit;
using MailKit.Net.Smtp;
using MimeKit;
using MimeKit.Text;
using System;
using System.Collections.Generic;
using System.Text;

namespace EmailHelper.SMTP
{
    /// <summary>
    /// 发邮件
    /// </summary>
    public class SMTPHelper
    {
        /// <summary>
        /// 获取smtpclient
        /// </summary>
        /// <param name="configurationEntity"></param>
        /// <returns></returns>
        public SmtpClient GetSmtpClient(ServerConfigurationEntity configurationEntity)
        {
            MailService mailService = new SmtpClient(new ProtocolLogger(EmailServerConnect.CreateMailLog())); //Pop3Client、SmtpClient
            SmtpClient client = null;

            bool res = EmailServerConnect.ConnectServer(mailService, configurationEntity);
            if (res)
            {
                client = (SmtpClient)mailService;
                if (client.IsConnected)
                {
                    return client;
                }
            }
            return null;
        }


        /// <summary>
        /// 获取MimeMessage
        /// </summary>
        /// <param name="mailInfo"></param>
        /// <returns></returns>
        private static MimeMessage GetMimeMessage(EmailInfo mailInfo)
        {
            try
            {
                if (mailInfo == null)
                    return null;
                var message = new MimeMessage();
                Contact from = mailInfo.From;
                if (from != null)
                {
                    message.From.Add(new MailboxAddress(from.Name, from.Address));
                }
                List<Contact> to = mailInfo.To;
                //InternetAddressList internetAddressesTo = message.To;
                if (to != null)
                {
                    foreach (var item in to)
                    {
                        message.To.Add(new MailboxAddress(item.Name, item.Address));
                    }
                }
                List<Contact> cc = mailInfo.CC;
                //InternetAddressList internetAddressesCc = message.Cc;
                if (cc != null)
                {
                    foreach (var item in cc)
                    {
                        message.Cc.Add(new MailboxAddress(item.Name, item.Address));
                    }
                }
                message.Subject = mailInfo.Subject;

                message.Body = mailInfo.Body;
                message.Priority = MessagePriority.Urgent;
                if (mailInfo.Headers != null)
                {
                    foreach (var item in mailInfo.Headers)
                    {
                        string[] s = item.Split('=');
                        message.Headers.Add(s[0], s[1]);
                    }
                }

                return message;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 测试发送邮件
        /// </summary>
        /// <param name="client"></param>
        /// <param name="emailInfo"></param>
        /// <returns></returns>
        public static SendResultEntity Send(SmtpClient client, EmailInfo emailInfo)
        {
            MimeMessage message = GetMimeMessage(emailInfo);
            if (message == null)
                return null;
            SendResultEntity sendResultEntity = new SendResultEntity();
            try
            {
                client.Send(message);
            }
            catch (SmtpCommandException ex)
            {
                switch (ex.ErrorCode)
                {
                    case SmtpErrorCode.RecipientNotAccepted:
                        sendResultEntity.ResultInformation = $"收件人未被接受:{ex.Message}";
                        break;
                    case SmtpErrorCode.SenderNotAccepted:
                        sendResultEntity.ResultInformation = $"发件人未被接受:{ex.Message}";
                        break;
                    case SmtpErrorCode.MessageNotAccepted:
                        sendResultEntity.ResultInformation = $"消息未被接受:{ex.Message}";
                        break;
                }
                sendResultEntity.ResultStatus = false;
            }
            catch (SmtpProtocolException ex)
            {
                sendResultEntity.ResultInformation = $"发送消息时的协议错误:{ex.Message}";
                sendResultEntity.ResultStatus = false;
            }
            catch (Exception ex)
            {
                sendResultEntity.ResultInformation = $"邮件接收失败:{ex.Message}";
                sendResultEntity.ResultStatus = false;
            }
            return sendResultEntity;
        }


        /// <summary>
        /// 通用发送邮件
        /// </summary>
        /// <param name="messge"></param>
        /// <param name="serverConfigurationEntity"></param>
        /// <returns></returns>
        public static SendResultEntity Send(EmailModel messge, ServerConfigurationEntity serverConfigurationEntity)
        {
            SendResultEntity sendResultEntity = new SendResultEntity();
            MailService mailService = new SmtpClient();
            bool res = EmailServerConnect.ConnectServer(mailService, serverConfigurationEntity);
            if (res)
            {
                SmtpClient client = (SmtpClient)mailService;
                MimeMessage message = GetMimeMessage(GetEmailInfo(messge));
                if (message == null)
                {
                    return new SendResultEntity { ResultStatus = false, ResultInformation = "Wrong parameter" };
                }
                try
                {
                    client.Send(message);
                }
                catch (SmtpCommandException ex)
                {
                    switch (ex.ErrorCode)
                    {
                        case SmtpErrorCode.RecipientNotAccepted:
                            sendResultEntity.ResultInformation = $"Recipient not accepted:{ex.Message}";
                            break;
                        case SmtpErrorCode.SenderNotAccepted:
                            sendResultEntity.ResultInformation = $"The sender was not accepted:{ex.Message}";
                            break;
                        case SmtpErrorCode.MessageNotAccepted:
                            sendResultEntity.ResultInformation = $"Message not accepted:{ex.Message}";
                            break;
                    }
                    sendResultEntity.ResultStatus = false;
                }
                catch (SmtpProtocolException ex)
                {
                    sendResultEntity.ResultInformation = $"Protocol error sending message:{ex.Message}";
                    sendResultEntity.ResultStatus = false;
                }
                catch (Exception ex)
                {
                    sendResultEntity.ResultInformation = $"Mail receiving failed:{ex.Message}";
                    sendResultEntity.ResultStatus = false;
                }
            }
            else
            {
                sendResultEntity.ResultStatus = false;
                sendResultEntity.ResultInformation = "Failed to connect to server";
            }
            return sendResultEntity;
        }
        /// <summary>
        /// 获取邮件信息
        /// </summary>
        /// <param name="messge"></param>
        /// <returns></returns>
        private static EmailInfo GetEmailInfo(EmailModel messge)
        {
            if (messge == null)
                return null;

            EmailInfo emailInfo = new EmailInfo()
            {
                From = messge.From,
                To = messge.To,
                CC = messge.CC,
                Subject = messge.Subject,
            };
            if (emailInfo != null)
            {
                if (string.IsNullOrEmpty(messge.Subject))
                {
                    emailInfo.Subject = "No Subject";
                }
                var html = new TextPart(TextFormat.Html)
                {
                    Text = messge.Message
                };
                var alternative = new Multipart("alternative");
                alternative.Add(html);
                // now create the multipart/mixed container to hold the message text and the
                // image attachment
                var multipart = new Multipart("mixed");
                multipart.Add(alternative);
                emailInfo.Body = multipart;
            }
            return emailInfo;
        }

    }
}